import { v4 as uuid } from "uuid";

//获取子文件（夹）
const judgePidChildren = (pid, filesObj, foldersObj) => {
  const childArr = [];
  for (let i in filesObj) {
    const v = filesObj[i];
    if (v.pid === pid) {
      childArr.push({
        //true代表文件类型，false代表文件夹类型
        id: i,
        bFile: true,
      });
    }
  }
  for (let i in foldersObj) {
    const v = foldersObj[i];
    if (v.pid === pid) {
      childArr.push({
        //true代表文件类型，false代表文件夹类型
        id: i,
        bFile: false,
      });
    }
  }
  return childArr;
};
//获取所有文件（夹），包括嵌套的
const judgePidAllChildren = (pid, filesObj, foldersObj) => {
  console.log("获取所有pid");
  const childArr = [];
  for (let i in filesObj) {
    const v = filesObj[i];
    if (v.pid === pid) {
      childArr.push({
        //true代表文件类型，false代表文件夹类型
        id: i,
        bFile: true,
      });
    }
  }
  for (let i in foldersObj) {
    const v = foldersObj[i];
    if (v.pid === pid) {
      childArr.push({
        //true代表文件类型，false代表文件夹类型
        id: i,
        bFile: false,
      });

      const innerChildren = judgePidAllChildren(i, filesObj, foldersObj);
      if (innerChildren.length) {
        childArr.push(...innerChildren);
      }
    }
  }
  return childArr;
};

const getChildren = (pid, filesObj, foldersObj) => {
  //1、返回值是对象数组，对象有title、key和isLeaf属性
  //获取当前pid下的子id集合
  const childs = judgePidChildren(pid, filesObj, foldersObj);
  return childs.map((item) => {
    const { id, bFile } = item;
    if (bFile) {
      return {
        title: filesObj[id].name,
        key: id,
        isLeaf: true,
      };
    } else {
      //文件夹,isLeaf永远为false
      const innerChildren = getChildren(id, filesObj, foldersObj);
      if (innerChildren.length) {
        return {
          title: foldersObj[id].name,
          key: id,
          children: getChildren(id, filesObj, foldersObj),
        };
      } else {
        return {
          title: foldersObj[id].name,
          key: id,
        };
      }
    }
  });
};
/**
 * 删除指定id下的所有文件和文件夹，返回一个新对象
 * @param {*} pid
 * @param {*} files
 */
export const deleteChildren = (pid, files) => {
  const { filesObj, foldersObj } = files;
  //删除所有子文件和子文件夹
  const newFileObj = { ...filesObj };
  const newFoldersObj = { ...foldersObj };
  //首先删除自身
  delete newFoldersObj[pid];
  //循环获取所有子文件（夹）并删除
  const childs = judgePidAllChildren(pid, filesObj, foldersObj);
  childs.forEach((item) => {
    const { id, bFile } = item;
    if (bFile) {
      //子文件，直接删除即可
      delete newFileObj[id];
    } else {
      //子文件夹，嵌套删除
      delete newFoldersObj[id];
    }
  });
  return { ...files, filesObj: newFileObj, foldersObj: newFoldersObj };
};
/**
 * store中的文件数据转树状图所需数据
 * @param {*} oriObj
 */
export const convertStoreToTreeData = (oriObj) => {
  const { filesObj, foldersObj } = oriObj;

  const obj = {};

  //找根元素的子文件和子文件
  obj.title = foldersObj[0].name;
  obj.key = "0";
  const children = getChildren(0, filesObj, foldersObj);
  if (children.length) {
    obj.children = children;
  }

  return [obj];
};
/**
 * 获取文件后缀名，不含点号
 * @param {string} filePathWithName 文件路径
 */
export const getExtFromFile = (filePathWithName) => {
  const index = filePathWithName.lastIndexOf(".");
  if (index > 0) {
    return filePathWithName.slice(index + 1);
  } else {
    return "";
  }
};

const getSubObjArr = (filesObj, foldersObj, copyId, pid) => {
  const resArr = [];
  //文件夹id
  const curentFolder = foldersObj[copyId];
  const newFolderId = uuid();
  //首先复制当前文件夹
  resArr.push({
    type: "folder",
    data: {
      id: newFolderId,
      name: curentFolder.name,
      pid: pid === "0" ? 0 : pid,
    },
  });
  //子文件(夹)
  const childArr = judgePidChildren(copyId, filesObj, foldersObj);
  if (childArr.length) {
    childArr.forEach((item) => {
      const childId = item.id;
      const bFile = item.bFile;
      if (bFile) {
        const newFileID = uuid();
        resArr.push({
          type: "file",
          data: {
            id: newFileID,
            name: filesObj[childId].name,
            content: filesObj[childId].content,
            pid: newFolderId,
          },
        });
      } else {
        //文件夹
        resArr.push(
          ...getSubObjArr(filesObj, foldersObj, childId, newFolderId)
        );
      }
    });
  }
  return resArr;
};

const copyFolder = (files, copyId, pid) => {
  debugger;
  const { filesObj, foldersObj } = files;
  const resArr = getSubObjArr(filesObj, foldersObj, copyId, pid);
  console.log(resArr);
  //1、先生成自身文件夹对象并添加
  const newFoldersObj = { ...foldersObj };
  const newFilesObj = { ...filesObj };
  resArr.forEach((item) => {
    const {
      type,
      data: { id, name, content, pid },
    } = item;
    if (type === "file") {
      //文件
      newFilesObj[id] = {
        name,
        content,
        pid: pid === "0" ? 0 : pid,
      };
    } else {
      //文件夹
      newFoldersObj[id] = {
        name,
        pid: pid === "0" ? 0 : pid,
      };
    }
  });

  return {
    ...files,
    filesObj: newFilesObj,
    foldersObj: newFoldersObj,
    copyId: "",
    clipFileId: "",
    clipFileObj: {},
  };
};

/**
 * 粘贴
 * @param {*} pid
 * @param {*} preState
 */
export const doPaste = (pid, preState) => {
  const { filesObj, foldersObj, copyId, clipFileId, clipedFileObj } = preState;
  //经过代码的设计让copyId和clipFileId互斥，一个有值，另一个就没值
  if (copyId) {
    //有值，代表粘贴的是复制的内容
    if (Object.keys(filesObj).includes(copyId)) {
      //粘贴的是文件
      //1、复制一份，重新生成一个id，pid指向修改即可
      return {
        ...preState,
        clipFileId: "",
        copyId: "",
        clipedFileObj: {},
        filesObj: {
          ...filesObj,
          [uuid()]: {
            ...filesObj[copyId],
            pid: pid === "0" ? 0 : pid,
          },
        },
      };
    } else {
      //粘贴的是复制的文件夹
      // const childArr = judgePidAllChildren(copyId, filesObj, foldersObj)
      debugger;
      return copyFolder(preState, copyId, pid);

      //子元素
    }
  } else {
    //没有值，代表粘贴的是剪切的内容
    if (clipedFileObj.type === "file") {
      //粘贴文件
      //1、剪切文件并粘贴，pid指向修改即可
      return {
        ...preState,
        clipFileId: "",
        copyId: "",
        clipedFileObj: {},
        filesObj: {
          ...filesObj,
          [clipFileId]: {
            name: clipedFileObj.name,
            content: clipedFileObj.content,
            pid: pid === "0" ? 0 : pid,
          },
        },
      };
    } else {
      //粘贴剪切的文件夹
      //1、还原被剪切的文件夹对象，修改其pid指向即可
      return {
        ...preState,
        clipFileId: "",
        copyId: "",
        clipedFileObj: {},
        foldersObj: {
          ...foldersObj,
          [clipFileId]: {
            name: clipedFileObj.name,
            conetent: clipedFileObj.content,
            pid: pid === "0" ? 0 : pid,
          },
        },
      };
    }
  }
};
/**
 * 剪切文件或者文件夹
 * @param {*} payload
 * @param {*} filesObj
 * @param {*} foldersObj
 * @param {*} preState
 */
export const clipFileOrFolder = (payload, filesObj, foldersObj, preState) => {
  //更新剪切板
  const id = payload;
  const { openedFilesIdArr, activeFileId } = preState;
  const newFilesObj = { ...filesObj };
  const newFoldersObj = { ...foldersObj };
  let newOpenedFilesIdArr = [...openedFilesIdArr];
  let newActiveFileId = activeFileId;
  //如果id有值，代表正在进行剪切操作，需要将当前文件或者文件夹删除
  let originObj = {};
  if (id === "") {
    //如果id没有值，代表更新为空
    return {
      ...preState,
      clipFileId: "",
      clipedFileObj: {},
    };
  }
  if (Object.keys(filesObj).includes(id)) {
    originObj = {
      type: "file",
      ...newFilesObj[id],
    };
    delete newFilesObj[id];
  } else {
    originObj = {
      type: "folder",
      ...newFoldersObj[id],
    };
    //如果打开的文件被关闭或者删除，都需要动态修改
    const childArr = judgePidAllChildren(id, filesObj, foldersObj);
    debugger;
    const removedOpenArr = [];
    childArr.forEach((item) => {
      const childId = item.id;
      if (item.bFile) {
        const index = openedFilesIdArr.indexOf(childId);
        if (index >= 0) {
          //删除这个数据
          removedOpenArr.push(childId);
        }
      }
    });
    newOpenedFilesIdArr = openedFilesIdArr.filter(
      (item) => removedOpenArr.includes(item) === false
    );
    delete newFoldersObj[id];
  }

  return {
    ...preState,
    clipFileId: id,
    clipedFileObj: originObj,
    filesObj: newFilesObj,
    foldersObj: newFoldersObj,
    //重置copyId
    copyId: "",
    activeFileId: newActiveFileId,
    openedFilesIdArr: newOpenedFilesIdArr,
  };
};
